"""
笔迹协议可以分为两层
1. 应用层: 存储笔迹的原始数据
2. 传输层: 在笔迹的原始数据上封装了用户的id
"""
from functools import cached_property
import time

TIMESTAMP_LENGTH = 6


class TransportFrame:
    def __init__(self, action, user_id, value, raw=None):
        self.action = action
        self.user_id = user_id
        self.value = value
        self._raw = raw

    @cached_property
    def data_frame(self):
        return DataFrame.from_bytes(self.value)

    @classmethod
    def from_bytes(cls, binary_value, with_timestamp=False):
        if with_timestamp:
            binary_value = cls.unpack_timestamp(binary_value)
        action = binary_value[0]
        user_id = int.from_bytes(binary_value[1:6], 'big')
        value = binary_value[6:]
        return cls(action, user_id, value, raw=binary_value)

    @staticmethod
    def pack_timestamp(binary_value):
        timestamp = int(time.time() * 1000)
        timestamp = timestamp.to_bytes(TIMESTAMP_LENGTH, 'big')
        return timestamp + binary_value

    @staticmethod
    def unpack_timestamp(binary_value):
        return binary_value[TIMESTAMP_LENGTH:]

    def to_bytes(self):
        if self._raw is None:
            self._raw = self.action.to_bytes(1, 'big')
            self._raw += self.user_id.to_bytes(5, 'big')
            self._raw += self.value
        return self._raw


class DataFrame:
    def __init__(self, action, value, raw=None):
        self.action = action
        self.value = value
        self._raw = raw

    def to_bytes(self):
        if self._raw is None:
            self._raw = self.action.to_bytes(1, 'bit')
            self._raw += self.value
        return self._raw

    @classmethod
    def from_bytes(cls, binary_value):
        action = binary_value[0]
        value = binary_value[1:]
        return cls(action, value, raw=binary_value)
